#ifndef SLTOOL_RWLOCK_20220426_
#define SLTOOL_RWLOCK_20220426_

//写优先读写锁
//#include <thread>
#include <mutex>
//#include <list>
//#include <vector>
#include <condition_variable>

class SLT_rwlock
{
public:
	SLT_rwlock() {}
	~SLT_rwlock() {};

	void readLock() {
		std::unique_lock<std::mutex> uniLock(mMyMutex);
		if (mWritingThreadNum || mWaitWriteTrheadNum) { //写优先，只要有线程在等待写，则不能让读线程得到机会。
			++mWaitReadThreadNum;
			while (mWritingThreadNum || mWaitWriteTrheadNum) {
				mReadThreadCV.wait(uniLock);
			}
			--mWaitReadThreadNum;
		}
		++mReadingThreadNum;
	}

	void writeLock() {
		std::unique_lock<std::mutex> uniLock(mMyMutex);
		if (mWritingThreadNum || mReadingThreadNum) {
			++mWaitWriteTrheadNum;
			while (mWritingThreadNum || mReadingThreadNum) {
				mWriteThreadCV.wait(uniLock);
			}
			--mWaitWriteTrheadNum;
		}
		++mWritingThreadNum;
	}

	void unReadLock() {
		std::unique_lock<std::mutex> uniLock(mMyMutex);
		--mReadingThreadNum;
		if (mWaitWriteTrheadNum) {//有写线程在等待的话，直接尝试唤醒一个写线程，即使还有其他线程在读。写优先！
			mWriteThreadCV.notify_one();
		}
	}

	void unWriteLock() {
		std::unique_lock<std::mutex> uniLock(mMyMutex);
		--mWritingThreadNum;
		if (mWaitWriteTrheadNum) {//写优先
			mWriteThreadCV.notify_one();
		}
		else {
			mReadThreadCV.notify_all();//通知所有被阻塞的read线程
		}
	}

private:
	int mWaitReadThreadNum = 0;
	int mReadingThreadNum = 0;
	int mWaitWriteTrheadNum = 0;
	int mWritingThreadNum = 0;

	std::mutex mMyMutex;
	std::condition_variable mReadThreadCV;//用于“读线程”的等待和唤醒。
	std::condition_variable mWriteThreadCV;//用于"写线程"的等待和唤醒
};

class SLT_autoRWLock
{
public:
	enum lock_opt{
		lock_read,
		lock_write
	};
	SLT_autoRWLock(SLT_rwlock* _lock, lock_opt _opt)
	{
		m_opt = _opt;
		m_lock = _lock;
		if (m_lock) {
			if (m_opt == lock_write) {
				m_lock->writeLock();
			}
			else {
				m_lock->readLock();
			}
		}
	}
	~SLT_autoRWLock() {
		if (m_lock) {
			if (m_opt == lock_write) {
				m_lock->unWriteLock();
			}
			else {
				m_lock->unReadLock();
			}
		}
	}
	lock_opt    m_opt = lock_write;
	SLT_rwlock* m_lock =NULL;
};

#endif